#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <jsoncpp/json/json.h>

using std::string;

const static string CONTENT_SEP = " ";
const static string PROTOCAL_SEP = "\n";

// 5|\n|1 op 2|\n
static string code(const string& content){
    string package = std::to_string(content.size());
    package += PROTOCAL_SEP;
    package += content;
    package += PROTOCAL_SEP;

    return package;
}

bool decode(string& package, string* content){
    auto left = package.find(PROTOCAL_SEP);
    if(left == string::npos){
        return false;
    }
    size_t len = std::stoi(package.substr(0, left));

    size_t allLen = left + len + 2; 
    if(package.size() < allLen){
        return false;
    }
    
    *content = package.substr(left + 1,  len);
    package.erase(0, allLen);

    return true;
}


class request
{
public:
    request(int a, int b, char op)
        :_a(a)
        ,_b(b)
        ,_op(op)
    {}
    request(){}

    // a op b
    bool serialize(string* content){
    #ifdef my
       
        string s = std::to_string(_a);
        s += CONTENT_SEP;
        s += _op;
        s += CONTENT_SEP;
        s += std::to_string(_b);

        *content = s;
       
        return true;

    #else
       
        Json::Value root;
        root["a"] = _a;
        root["b"] = _b;
        root["op"] = _op;

        Json::StyledWriter w;
        *content = w.write(root);
        
        return true;

    #endif
    }

    bool deserialize(const string& content){
#ifdef my
        auto left = content.find(CONTENT_SEP);
        if(left == string::npos){
            return false;
        }
        string cut = content.substr(0, left);
        _a = std::stoi(cut);

        auto right = content.rfind(CONTENT_SEP);
        if(right == string::npos){
            return false;
        }
        cut = content.substr(right + 1);
        _b = std::stoi(cut);

        if(left + 2 != right){
            return false;
        }
        _op = content[left + 1];

        return true;
#else
        Json::Value root;
        Json::Reader r;
        r.parse(content, root);

        _a = root["a"].asInt();
        _b = root["b"].asInt();
        _op = root["op"].asInt();

        return true;
#endif
    }

    void DebugPrint()
    {
        std::cout << "新请求构建完成:  " << _a << _op << _b << "=?" << std::endl;
    }

    int _a;
    int _b;
    char _op;
};

class response
{
public:
    response(int result, int code)
        :_result(result)
        ,_code(code)
    {}
    response(){}
    // r c
    bool serialize(string* content){
#ifdef my
        string s = std::to_string(_result);
        s += CONTENT_SEP;
        s += std::to_string(_code);

        *content = s;

        return true;
#else
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::StyledWriter w;
        w.write(*content);
        return true;
#endif
    }

    bool deserialize(const string& content){
#ifdef my
        auto left = content.find(CONTENT_SEP);
        if(left == string::npos){
            return false;
        }
        _result = std::stoi(content.substr(0, left));
        
        _code = std::stoi(content.substr(left + 1));

        return true;
#else

        Json::Value root;
        Json::Reader r;
        r.parse(content, root);

        _result = root["result"].asInt();
        _code = root["code"].asInt();

        return true;
#endif
    }

    void DebugPrint()
    {
        std::cout << "结果响应完成, result: " << _result << ", code: "<< _code << std::endl;
        printf("==========================\n");
    }

    int _result;
    int _code;
};
